package com.xinz.server;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.List;
import java.util.Map;

import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.DynamicChannelBuffer;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFutureListener;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
import org.jboss.netty.handler.codec.frame.TooLongFrameException;
import org.jboss.netty.handler.codec.http.DefaultHttpResponse;
import org.jboss.netty.handler.codec.http.HttpRequest;
import org.jboss.netty.handler.codec.http.HttpResponse;
import org.jboss.netty.handler.codec.http.HttpResponseStatus;
import org.jboss.netty.handler.codec.http.HttpVersion;
import org.jboss.netty.handler.codec.http.QueryStringDecoder;
import org.jboss.netty.util.CharsetUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.xinz.command.Command;
import com.xinz.command.CommandSet;

/**
 * 管理接口接受请求处理
 *
 */
public class SpotAdminServerHandler extends SimpleChannelUpstreamHandler {

	private static final Logger log = LoggerFactory.getLogger(SpotAdminServerHandler.class);
	
	private static final Logger logFlow = LoggerFactory.getLogger("FLOW");
	
	@Override
	public void messageReceived(ChannelHandlerContext ctx, MessageEvent messageEvent) {
		Channel channel = messageEvent.getChannel();
		long startTime = System.currentTimeMillis();
		String cmd = "";
		String playerId = null;
		try {
			HttpRequest request = (HttpRequest) messageEvent.getMessage();
			String uri = request.getUri();
			
			try {
				uri = URLDecoder.decode(uri, "utf-8");
			}
			catch(UnsupportedEncodingException e) {
				log.error(e.getMessage());
			}
			
			uri = uri.substring(1).replace("?", "").replace("cmd=", "");
			
			// post请求和get请求
			ChannelBuffer cb = request.getContent();
			Map<String, List<String>> params = null;
			if(cb.readable()) { // post请求
				String param = cb.toString(CharsetUtil.UTF_8);
				QueryStringDecoder queryStringDecoder = new QueryStringDecoder("/?" + param);
				params = queryStringDecoder.getParameters();
			}
			
			String[] msgArray = uri.split("|");
			int psLen = msgArray.length;
			cmd = msgArray[0];
			if(psLen >= 2) {
				playerId = msgArray[1];
			}
			
			String[] args = null;
			if(psLen >= 3) { // 参数使用"_"
				String psStr = msgArray[2];
				args = psStr.split("_");
			}
			
			//  执行cmd
			Command command = CommandSet.getInstance().getCommand(cmd);
			if(command == null) {
				throw new Exception("cmd invalid,cmd=" + command);
			}
			String result = command.execute(playerId, args);
			// 输出
			print(channel, result);
		}
		catch(Exception e) {
			log.error(e.getMessage(), e);
			print(channel, e.getMessage());
		}
		finally {
			long endTime = System.currentTimeMillis();
			logFlow.info(cmd + "|" + playerId + "|" + (endTime - startTime));
		}
	}
	
	/**
	 * 输出
	 * @param channel
	 * @param content
	 */
	private void print(Channel channel, String content) {
		HttpResponse response = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
		response.setHeader("Content-Type", "text/javascript; charset=utf-8");
		ChannelBuffer buffer = new DynamicChannelBuffer(2048);
		try {
			buffer.writeBytes(content.getBytes("utf-8"));
		}
		catch(UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		response.setContent(buffer);
		channel.write(response).addListener(ChannelFutureListener.CLOSE);
	}
	
	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
		Channel ch = e.getChannel();
		Throwable cause = e.getCause();
		if(cause instanceof TooLongFrameException) {
			sendError(ctx, HttpResponseStatus.BAD_REQUEST);
			return;
		}
		cause.printStackTrace();
		if(ch.isConnected()) {
			sendError(ctx, HttpResponseStatus.INTERNAL_SERVER_ERROR);
		}
		ch.close();
	}
	
	private void sendError(ChannelHandlerContext ctx, HttpResponseStatus status) throws UnsupportedEncodingException {
		Channel channel = ctx.getChannel();
		print(channel, "Error");
	}
}
